package cn.tedu.mall.front.service.impl;

import cn.tedu.mall.common.exception.CoolSharkServiceException;
import cn.tedu.mall.common.restful.ResponseCode;
import cn.tedu.mall.front.service.IFrontCategoryService;
import cn.tedu.mall.pojo.front.entity.FrontCategoryEntity;
import cn.tedu.mall.pojo.front.vo.FrontCategoryTreeVO;
import cn.tedu.mall.pojo.product.vo.CategoryStandardVO;
import cn.tedu.mall.product.service.ICategoryService;
import cn.tedu.mall.product.service.front.IForFrontCategoryService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@DubboService
@Service
@Slf4j
public class FrontCategoryServiceImpl implements IFrontCategoryService {
    @DubboReference
    private IForFrontCategoryService dubboCategoryService;
    @Autowired
    private RedisTemplate redisTemplate;

    public static final String CATEGORY_TREE_KEY = "category_tree";

    @Override
    public FrontCategoryTreeVO categoryTree() {
        log.info("开始执行查询分类列表...");
        //检查Redis是否已经保存了含有三级分类的对象
        if (redisTemplate.hasKey(CATEGORY_TREE_KEY)) {
            FrontCategoryTreeVO<FrontCategoryEntity> treeVO = (FrontCategoryTreeVO<FrontCategoryEntity>)
                    redisTemplate.boundValueOps(CATEGORY_TREE_KEY).get();
            log.info("从缓存中查询获得分类数据");
            return treeVO;
        }
        // Redis中没有三级分类树信息,表示本次请求可能是首次访问
        // dubbo调用查询所有分类对象的方法
        List<CategoryStandardVO> categoryStandardVOs = dubboCategoryService.getCategoryList();
        // 我们需要将没有关联子分类能力的CategoryStandardVO类型
        // 转换为具备关联子分类能力的FrontCategoryEntity类型
        // 并将正确的父子分类关系保存构建起来,最好编写一个单独的方法
        FrontCategoryTreeVO<FrontCategoryEntity> treeVO = initTree(categoryStandardVOs);
        // 上面已经完成了三级分类树的构建,下面要将返回值treeVO
        // 保存在redis中,方便后面请求的访问
        redisTemplate.boundValueOps(CATEGORY_TREE_KEY).set(treeVO, 1, TimeUnit.MINUTES);
        log.info("从数据库中查询获得分类数据");
        return treeVO;
    }

    /**
     * 从数据库中查询到的分类对象转换为三级分类树的方法
     *
     * @param categoryStandardVOs 分类对象
     * @return 包含三级分类树的对象
     */
    private FrontCategoryTreeVO<FrontCategoryEntity> initTree(List<CategoryStandardVO> categoryStandardVOs) {
        Map<Long, List<FrontCategoryEntity>> map = new HashMap<>();
        log.info("当前分类对象总数:{}", categoryStandardVOs.size());
        // 第一步:
        // 确实所有分类对象的父分类id
        // 以父分类id为key,将相同父分类的子分类对象保存到同一个Map的key中
        // 一个父分类可能包含多个子分类,所有这个Map的value是一个List
        for (CategoryStandardVO categoryStandardVO : categoryStandardVOs) {
            FrontCategoryEntity frontCategoryEntity = new FrontCategoryEntity();
            BeanUtils.copyProperties(categoryStandardVO, frontCategoryEntity);

            Long parentId = frontCategoryEntity.getParentId();
            if (map.containsKey(parentId)) {
                map.get(parentId).add(frontCategoryEntity);

            } else {
                ArrayList<FrontCategoryEntity> value = new ArrayList<>();
                value.add(frontCategoryEntity);
                map.put(parentId, value);
            }
        }
        // 第二步:
        // 将子分类对象关联到父分类对象的children属性中
        // 下面操作应该从一级分类开始,我们先通过0作为父分类id获得所有一级分类
        List<FrontCategoryEntity> firstLevels = map.get(0L);
        if (firstLevels == null || firstLevels.isEmpty()) {
            throw new CoolSharkServiceException(
                    ResponseCode.INTERNAL_SERVER_ERROR, "没有一级分类"
            );
        }
        for (FrontCategoryEntity oneLevel : firstLevels) {
            Long secondLevelParentId = oneLevel.getId();
            List<FrontCategoryEntity> secondLevels = map.get(secondLevelParentId);
            if (secondLevels == null || secondLevels.isEmpty()) {
                log.warn("当前分类没有二级分类内容:{}", +secondLevelParentId);
                continue;
            }
            for (FrontCategoryEntity twoLevel : secondLevels) {
                Long thirdLevelParentId = twoLevel.getId();
                List<FrontCategoryEntity> thirdLevels = map.get(thirdLevelParentId);
                if (thirdLevels == null || thirdLevels.isEmpty()) {
                    log.warn("当前分类没有三级分类内容:{}", +thirdLevelParentId);
                    continue;
                }
                twoLevel.setChildrens(thirdLevels);
            }
            oneLevel.setChildrens(secondLevels);
        }
        FrontCategoryTreeVO<FrontCategoryEntity> treeVO = new FrontCategoryTreeVO<>();
        treeVO.setCategories(firstLevels);

        return treeVO;
    }
}













